home *** CD-ROM | disk | FTP | other *** search
- {===========================================================================
- Date: 08-31-93 (22:24)
- From: WIM VAN.VOLLENHOVEN
- Subj: Sound Module
- ---------------------------------------------------------------------------
- Well.. here is the source code i've found in a pascal toolbox (ECO)
- which emulates the play function of qbasic :-)
-
- {
- call: play(string)
-
- music_string --- the string containing the encoded music to be
- played. the format is the same as that of the
- microsoft basic play statement. the string
- must be <= 254 characters in length.
-
- calls: sound
- getint (internal)
-
- remarks: the characters accepted by this routine are:
-
- a - g musical notes
- # or + following a - g note, indicates sharp
- - following a - g note, indicates flat
- < move down one octave
- > move up one octave
- . dot previous note (extend note duration by 3/2)
- mn normal duration (7/8 of interval between notes)
- ms staccato duration
- ml legato duration
- ln length of note (n=1-64; 1=whole note,4=quarter note)
- pn pause length (same n values as ln above)
- tn tempo,n=notes/minute (n=32-255,default n=120)
- on octave number (n=0-6,default n=4)
- nn play note number n (n=0-84)
-
- the following two commands are ignored by play:
-
- mf complete note before continuing
- mb another process may begin before speaker is
- finished playing note
-
- important --- setdefaultnotes must have been called at least once before
- this routine is called.
- }
-
- unit u_play;
- interface
-
- uses
- crt
-
- ;
-
- const
- note_octave : integer = 4; { current octave for note }
- note_fraction : real = 0.875; { fraction of duration given to note }
- note_duration : integer = 0; { duration of note ^^semi-legato }
- note_length : real = 0.25; { length of note }
- note_quarter : real = 500.0; { moderato pace (principal beat) }
-
-
-
- procedure quitsound;
- procedure startsound;
- procedure errorbeep;
- procedure warningbeep;
- procedure smallbeep;
- procedure setdefaultnotes;
- procedure play(s: string);
- procedure beep(h, l: word);
-
-
-
- implementation
-
-
-
-
- procedure quitsound;
- var i: word;
- begin
- for i := 100 downto 1 do begin sound(i*10); delay(2) end;
- for i := 1 to 800 do begin sound(i*10); delay(2) end;
- nosound;
- end;
-
- procedure startsound;
- var i: word;
- begin
- for i := 100 downto 1 do begin sound(i*15); delay(2) end;
- for i := 1 to 100 do begin sound(i*15); delay(2) end; nosound;
- delay(100); for i := 100 downto 1 do begin sound(i*10); delay(2) end;
- nosound;
- end;
-
-
- procedure errorbeep;
- begin
- sound(2000); delay(75); sound(1000); delay(75); nosound;
- end;
-
-
- procedure warningbeep;
- begin
- sound(500); delay(500); nosound;
- end;
-
- procedure smallbeep;
- begin
- sound(300); delay(50); nosound;
- end;
-
-
-
-
-
- procedure setdefaultnotes;
- begin
- note_octave := 4; { default octave }
- note_fraction := 0.875; { default sustain is semi-legato }
- note_length := 0.25; { note is quarter note by default }
- note_quarter := 500.0; { moderato pace by default }
- end;
-
-
-
- procedure play(s: string);
- const
- { offsets in octave of natural notes }
- note_offset : array[ 'A'..'G' ] of integer = (9,11,0,2,4,5,7);
-
- { frequencies for 7 octaves }
- note_freqs: array[ 0 .. 84 ] of integer =
- {
- c c# d d# e f f# g g# a a# b
- }
- ( 0,
- 65, 69, 73, 78, 82, 87, 92, 98, 104, 110, 116, 123,
- 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
- 262, 278, 294, 312, 330, 350, 370, 392, 416, 440, 466, 494,
- 524, 556, 588, 624, 660, 700, 740, 784, 832, 880, 932, 988,
- 1048,1112,1176,1248,1320,1400,1480,1568,1664,1760,1864,1976,
- 2096,2224,2352,2496,2640,2800,2960,3136,3328,3520,3728,3952,
- 4192,4448,4704,4992,5280,5600,5920,6272,6656,7040,7456,7904 );
-
- quarter_note = 0.25; { length of a quarter note }
-
- digits : set of '0'..'9' = ['0'..'9'];
-
- var
-
- play_freq : integer; { frequency of note to be played }
- play_duration : integer; { duration to sound note }
- rest_duration : integer; { duration of rest after a note }
- i : integer; { offset in music string }
- c : char; { current character in music string }
- { note frequencies }
- freq : array[0..6,0..11] of integer absolute note_freqs;
- n : integer;
- xn : real;
- k : integer;
-
- function getint : integer;
- var n: integer;
-
- begin { getint }
- n := 0;
- while(s[i] in digits) do begin n := n*10+ord(s[i])-ord('0'); inc(i) end;
- dec(i); getint := n;
- end { getint };
-
- begin
- s := s + ' '; { append blank to end of music string }
- i := 1; { point to first character in music }
- while(i < length(s)) do begin { begin loop over music string }
- c := upcase(s[i]); { get next character in music string }
- case c of { interpret it }
- 'A'..'G' : begin { a note }
- n := note_offset[ c ];
- play_freq := freq[ note_octave ,n ];
- xn := note_quarter * (note_length / quarter_note);
- play_duration := trunc(xn * note_fraction);
- rest_duration := trunc(xn * (1.0 - note_fraction));
- { check for sharp/flat }
- if s[i+1] in ['#','+','-' ] then
- begin
- inc(i);
- case s[i] of
- '#',
- '+' : play_freq :=
- freq[ note_octave ,succ(n) ];
- '-' : play_freq :=
- freq[ note_octave ,pred(n) ];
- else ;
- end { case };
-
- end;
-
- { check for note length }
-
- if (s[i+1] in digits) then
- begin
-
- inc(i);
- n := getint;
- xn := (1.0 / n) / quarter_note;
-
- play_duration :=
- trunc(note_fraction * note_quarter * xn);
-
- rest_duration :=
- trunc((1.0 - note_fraction) *
- xn * note_quarter);
-
- end;
- { check for dotting }
-
- if s[i+1] = '.' then
- begin
-
- xn := 1.0;
-
- while(s[i+1] = '.') do
- begin
- xn := xn * 1.5;
- inc(i);
- end;
-
- play_duration :=
- trunc(play_duration * xn);
-
- end;
-
- { play the note }
-
- sound(play_freq);
- delay(play_duration);
- nosound;
- delay(rest_duration);
- end { a note };
-
- 'M' : begin { 'M' commands }
- inc(i);
- c := s[i];
- case c of
- 'F' : ;
- 'B' : ;
- 'N' : note_fraction := 0.875;
- 'L' : note_fraction := 1.000;
- 'S' : note_fraction := 0.750;
- else ;
- end { case };
- end { 'M' commands };
-
- 'O' : begin { set octave }
- inc(i);
- n := ord(s[i]) - ord('0');
- if (n < 0) or (n > 6) then n := 4;
- note_octave := n;
- end { set octave };
-
- '<' : begin { drop an octave }
- if note_octave > 0 then dec(note_octave);
- end { drop an octave };
-
- '>' : begin { ascend an octave }
- if note_octave < 6 then inc(note_octave);
- end { ascend an octave };
-
- 'N' : begin { play note n }
- inc(i); n := getint;
- if (n > 0) and (n <= 84) then begin
- play_freq := note_freqs[ n ];
- xn := note_quarter * (note_length / quarter_note);
- play_duration := trunc(xn * note_fraction);
- rest_duration := trunc(xn * (1.0 - note_fraction));
- end else if (n = 0) then begin
- play_freq := 0; play_duration := 0;
- rest_duration := trunc(note_fraction * note_quarter *
- (note_length / quarter_note));
- end;
- sound(play_freq); delay(play_duration); nosound;
- delay(rest_duration);
- end { play note n };
- 'L' : begin { set length of notes }
- inc(i); n := getint;
- if n > 0 then note_length := 1.0 / n;
- end { set length of notes };
-
- 'T' : begin { # of quarter notes in a minute }
- inc(i); n := getint;
- note_quarter := (1092.0 / 18.2 / n) * 1000.0;
- end { # of quarter notes in a minute };
-
- 'P' : begin { pause }
- inc(i); n := getint;
- if (n < 1) then n := 1 else if (n > 64) then n := 64;
- play_freq := 0; play_duration := 0;
- rest_duration := trunc(((1.0 / n) / quarter_note) * note_quarter);
- sound(play_freq); delay(play_duration); nosound;
- delay(rest_duration);
- end { pause };
-
- else { ignore other stuff };
- end { case };
- inc(i);
- end { interpret music };
- nosound; { make sure sound turned off when through }
- end;
-
-
- procedure beep(h, l: word);
- begin
- sound(h); delay(l); nosound;
- end;
-
- end. { of unit }